package io.wmy.supex.framework.config;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.util.PropertiesUtil;

import java.net.URI;

@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
@Order(50)
public class LogConfig extends ConfigurationFactory {

    static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
        PropertiesUtil prop =  new PropertiesUtil("supex.properties");
        String finalName = prop.getStringProperty("finalName");
        String logLevel = prop.getStringProperty("log.level").toUpperCase();
        String logDirs = prop.getStringProperty("log.dirs");
        String logPattern = prop.getStringProperty("log.pattern");
        String logAppendName = prop.getStringProperty("log.appendName");
        String logPackages = prop.getStringProperty("log.packages");

        builder.setConfigurationName(name);
        builder.setStatusLevel(Level.ERROR);

        LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout").addAttribute("pattern", logPattern);
        builder.add(builder.newAppender("Stdout", "CONSOLE")
                .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT).add(layoutBuilder));

        ComponentBuilder timeBasedTriggeringPolicy = builder.newComponent("Policies")
                        .addComponent(builder.newComponent("TimeBasedTriggeringPolicy")
                        .addAttribute("interval", "1")
                        .addAttribute("modulate", "true"));

        builder.add(builder.newAppender("InfoLogFile", "RollingFile")
                .addAttribute("fileName", logDirs + finalName + ".log")
                .addAttribute("filePattern", logDirs + finalName + "-%d{yyyyMMdd}.log")
                .addComponent(timeBasedTriggeringPolicy)
                .add(layoutBuilder));

        builder.add(builder.newAppender("ErrorLogFile", "RollingFile")
                .addAttribute("fileName", logDirs + finalName + "-error.log")
                .addAttribute("filePattern", logDirs + finalName + "-error-%d{yyyyMMdd}.log")
                .addComponent(timeBasedTriggeringPolicy)
                .add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.DENY).addAttribute("level", Level.ERROR))
                .add(layoutBuilder));

        builder.add(builder.newRootLogger(Level.getLevel(logLevel))
                .add(builder.newAppenderRef("Stdout"))
                .add(builder.newAppenderRef(logAppendName))
                .add(builder.newAppenderRef("ErrorLogFile")));

        builder.setPackages(logPackages);
        return builder.build();
    }

    @Override
    public Configuration getConfiguration(ConfigurationSource source) {
        return getConfiguration(source.toString(), null);
    }

    @Override
    public Configuration getConfiguration(final String name, final URI configLocation) {
        ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
        return createConfiguration(name, builder);
    }

    @Override
    protected String[] getSupportedTypes() {
        return new String[] {"*"};
    }
}